"""
推理模型响应处理器
专门处理推理模型（如deepseek-r1）的响应，过滤思考内容并智能解析JSON
"""

import json
import re
import ast
import logging
from typing import Dict, Optional, Any

logger = logging.getLogger(__name__)


class ReasoningResponseProcessor:
    """推理模型响应处理器"""

    def __init__(self):
        # 已知的推理模型（确定包含思考过程的模型）
        self.known_reasoning_models = {
            # DeepSeek推理模型
            'deepseek-r1', 'deepseek-r1-distill', 'deepseek-r1-zero',
            'deepseek-reasoner',

            # OpenAI推理模型
            'o1-preview', 'o1-mini', 'o1-pro',
            'o3-mini', 'o3-preview', 'o3-pro',

            # 通义千问推理模型
            'qwen-qvq', 'qwen-with-search',

            # 其他已知推理模型
            'claude-reasoning', 'glm-reasoning'
        }

        # 推理模型关键词（通用检测）
        self.reasoning_keywords = {
            'reasoning', 'reasoner', 'reason',
            'think', 'thinking', 'thought',
            'cot', 'chain-of-thought',
            'reflect', 'reflection',
            'analyze', 'analysis',
            'logic', 'logical',
            'step-by-step', 'stepwise',
            'deliberate', 'deliberation'
        }

        # 推理模型系列前缀（用于识别系列模型）
        self.reasoning_series = {
            'o1-', 'o2-', 'o3-', 'o4-',  # OpenAI o系列
            'r1-', 'r2-', 'r3-',         # 各种R系列
            'qvq-', 'think-'             # 其他推理系列
        }

    def is_reasoning_model(self, model_name: str) -> bool:
        """
        智能判断是否为推理模型

        检测策略：
        1. 已知推理模型精确匹配
        2. 推理关键词检测
        3. 推理系列前缀检测
        4. 环境变量手动指定
        """
        if not model_name:
            return False

        model_name = model_name.lower().strip()

        # 策略1: 检查已知推理模型
        if any(known_model in model_name for known_model in self.known_reasoning_models):
            logger.info(f"通过已知模型列表识别推理模型: {model_name}")
            return True

        # 策略2: 检查推理关键词
        if any(keyword in model_name for keyword in self.reasoning_keywords):
            logger.info(f"通过关键词识别推理模型: {model_name}")
            return True

        # 策略3: 检查推理系列前缀
        if any(model_name.startswith(prefix) for prefix in self.reasoning_series):
            logger.info(f"通过系列前缀识别推理模型: {model_name}")
            return True

        # 策略4: 检查环境变量手动指定
        import os
        manual_reasoning_models = os.getenv(
            'MANUAL_REASONING_MODELS', '').lower()
        if manual_reasoning_models and model_name in manual_reasoning_models.split(','):
            logger.info(f"通过环境变量手动指定识别推理模型: {model_name}")
            return True

        # 策略5: 检查是否在非推理模型黑名单中
        non_reasoning_keywords = {'chat', 'turbo',
                                  'flash', 'lite', 'mini', 'base', 'instruct'}
        # 如果模型名只包含非推理关键词且不包含推理关键词，则不是推理模型
        has_only_non_reasoning = any(
            keyword in model_name for keyword in non_reasoning_keywords)
        has_reasoning_indicator = any(
            keyword in model_name for keyword in self.reasoning_keywords)

        if has_only_non_reasoning and not has_reasoning_indicator:
            return False

        logger.debug(f"未识别为推理模型: {model_name}")
        return False

    def get_reasoning_detection_info(self, model_name: str) -> dict:
        """
        获取推理模型检测的详细信息

        Returns:
            包含检测结果和原因的字典
        """
        if not model_name:
            return {"is_reasoning": False, "reason": "模型名称为空"}

        model_name_lower = model_name.lower().strip()

        # 检查各种检测策略
        detection_results = {
            "model_name": model_name,
            "is_reasoning": False,
            "detection_method": None,
            "matched_pattern": None,
            "available_strategies": {
                "known_models": any(known_model in model_name_lower for known_model in self.known_reasoning_models),
                "keywords": any(keyword in model_name_lower for keyword in self.reasoning_keywords),
                "series_prefix": any(model_name_lower.startswith(prefix) for prefix in self.reasoning_series),
                "manual_config": False
            }
        }

        # 检查环境变量配置
        import os
        manual_reasoning_models = os.getenv(
            'MANUAL_REASONING_MODELS', '').lower()
        if manual_reasoning_models and model_name_lower in manual_reasoning_models.split(','):
            detection_results["available_strategies"]["manual_config"] = True

        # 确定最终结果和检测方法
        if detection_results["available_strategies"]["known_models"]:
            detection_results["is_reasoning"] = True
            detection_results["detection_method"] = "已知推理模型列表"
            for known_model in self.known_reasoning_models:
                if known_model in model_name_lower:
                    detection_results["matched_pattern"] = known_model
                    break
        elif detection_results["available_strategies"]["keywords"]:
            detection_results["is_reasoning"] = True
            detection_results["detection_method"] = "推理关键词检测"
            for keyword in self.reasoning_keywords:
                if keyword in model_name_lower:
                    detection_results["matched_pattern"] = keyword
                    break
        elif detection_results["available_strategies"]["series_prefix"]:
            detection_results["is_reasoning"] = True
            detection_results["detection_method"] = "推理系列前缀检测"
            for prefix in self.reasoning_series:
                if model_name_lower.startswith(prefix):
                    detection_results["matched_pattern"] = prefix
                    break
        elif detection_results["available_strategies"]["manual_config"]:
            detection_results["is_reasoning"] = True
            detection_results["detection_method"] = "环境变量手动指定"
            detection_results["matched_pattern"] = model_name_lower
        else:
            detection_results["detection_method"] = "未匹配任何推理模型模式"

        return detection_results

    def process_response(self, content: str, model_name: str = None) -> str:
        """
        处理推理模型响应

        Args:
            content: 原始响应内容
            model_name: 模型名称

        Returns:
            处理后的内容
        """
        if not content:
            return content

        logger.info(f"开始处理推理模型响应，模型: {model_name}, 原始长度: {len(content)}")

        # 如果不是推理模型，直接返回
        if not self.is_reasoning_model(model_name):
            logger.info("非推理模型，直接返回原始内容")
            return content

        # 移除思考内容
        cleaned_content = self._remove_thinking_content(content)
        logger.info(f"移除思考内容后长度: {len(cleaned_content)}")

        # 智能提取有效内容
        final_content = self._extract_valid_content(cleaned_content)
        logger.info(f"最终处理后长度: {len(final_content)}")

        return final_content

    def _remove_thinking_content(self, content: str) -> str:
        """移除思考内容"""
        if not content:
            return content

        # 移除XML风格的思考标签
        xml_patterns = [
            r'<think>.*?</think>',
            r'<thinking>.*?</thinking>',
            r'<thought>.*?</thought>',
            r'<reasoning>.*?</reasoning>'
        ]

        for pattern in xml_patterns:
            content = re.sub(pattern, '', content,
                             flags=re.DOTALL | re.IGNORECASE)

        # 移除中文思考标识
        chinese_patterns = [
            r'思考：.*?(?=\n\n|\n[^思考推理分析]|$)',
            r'推理：.*?(?=\n\n|\n[^思考推理分析]|$)',
            r'分析：.*?(?=\n\n|\n[^思考推理分析]|$)'
        ]

        for pattern in chinese_patterns:
            content = re.sub(pattern, '', content, flags=re.DOTALL)

        # 移除英文思考段落
        english_patterns = [
            r'Let me think.*?(?=\n\n|\n[A-Z]|$)',
            r'I need to think.*?(?=\n\n|\n[A-Z]|$)',
            r'First, let me.*?(?=\n\n|\n[A-Z]|$)',
            r'Let me analyze.*?(?=\n\n|\n[A-Z]|$)'
        ]

        for pattern in english_patterns:
            content = re.sub(pattern, '', content, flags=re.DOTALL)

        return content.strip()

    def _extract_valid_content(self, content: str) -> str:
        """智能提取有效内容"""
        if not content:
            return content

        # 尝试查找JSON内容
        try:
            json_content = self._find_complete_json_with_test_cases(content)
            if json_content and json_content.strip():
                logger.info("成功提取JSON内容")
                return json_content
        except Exception as e:
            logger.warning(f"JSON提取失败: {str(e)}")

        # 如果没有找到JSON，返回清理后的原始内容
        logger.info("未找到JSON，返回清理后的原始内容")
        return self._clean_content(content)

    def _find_complete_json_with_test_cases(self, content: str) -> Optional[str]:
        """查找完整的包含test_cases的JSON对象"""
        if not content:
            return None

        # 使用简单但可靠的方法
        brace_count = 0
        start_pos = -1

        for i, char in enumerate(content):
            if char == '{':
                if brace_count == 0:
                    start_pos = i
                brace_count += 1
            elif char == '}':
                brace_count -= 1
                if brace_count == 0 and start_pos != -1:
                    # 找到完整的JSON块
                    json_candidate = content[start_pos:i + 1]
                    try:
                        parsed = json.loads(json_candidate)
                        if isinstance(parsed, dict) and 'test_cases' in parsed:
                            return json_candidate
                    except json.JSONDecodeError:
                        continue

        return None

    def _clean_content(self, content: str) -> str:
        """清理内容"""
        if not content:
            return content

        # 移除多余的空白
        content = re.sub(r'\n\s*\n\s*\n+', '\n\n', content)
        content = re.sub(r'[ \t]+', ' ', content)

        # 移除控制字符
        content = re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]', '', content)

        return content.strip()

    def smart_parse_content(self, content: str) -> Optional[Dict[str, Any]]:
        """
        智能解析内容，支持多种格式

        Args:
            content: 要解析的内容

        Returns:
            解析后的字典，如果解析失败返回None
        """
        if not content or not content.strip():
            return None

        content = content.strip()
        logger.info(f"开始智能解析内容，长度: {len(content)}")

        # 策略1: 直接JSON解析
        try:
            result = json.loads(content)
            if isinstance(result, dict):
                logger.info("直接JSON解析成功")
                if 'test_cases' in result:
                    logger.info(
                        f"直接JSON解析找到test_cases，包含{len(result['test_cases'])}个用例")
                    return result
                else:
                    logger.debug("直接JSON解析成功但未找到test_cases字段")
            else:
                logger.debug(f"直接JSON解析结果类型不是dict: {type(result)}")
        except json.JSONDecodeError as e:
            logger.debug(f"直接JSON解析失败: {e}")

        # 策略2: Python字典解析
        try:
            # 安全地评估Python字典字符串
            result = ast.literal_eval(content)
            if isinstance(result, dict):
                logger.info("Python字典解析成功")
                if 'test_cases' in result:
                    logger.info(
                        f"Python字典解析找到test_cases，包含{len(result['test_cases'])}个用例")
                    return result
                else:
                    logger.debug("Python字典解析成功但未找到test_cases字段")
        except (ValueError, SyntaxError) as e:
            logger.debug(f"Python字典解析失败: {e}")

        # 策略3: 修复常见JSON问题后解析
        try:
            fixed_content = self._fix_json_issues(content)
            if fixed_content:
                result = json.loads(fixed_content)
                if isinstance(result, dict):
                    logger.info("修复JSON问题后解析成功")
                    if 'test_cases' in result:
                        logger.info(
                            f"修复JSON后找到test_cases，包含{len(result['test_cases'])}个用例")
                        return result
                    else:
                        logger.debug("修复JSON解析成功但未找到test_cases字段")
            else:
                logger.debug("JSON修复失败，无法生成有效内容")
        except json.JSONDecodeError as e:
            logger.debug(f"修复JSON问题后解析失败: {e}")

        # 策略4: 提取JSON片段
        try:
            json_content = self._find_complete_json_with_test_cases(content)
            if json_content:
                logger.debug(f"找到JSON片段，长度: {len(json_content)}")
                result = json.loads(json_content)
                if isinstance(result, dict):
                    logger.info("提取JSON片段后解析成功")
                    if 'test_cases' in result:
                        logger.info(
                            f"JSON片段找到test_cases，包含{len(result['test_cases'])}个用例")
                        return result
                    else:
                        logger.debug("JSON片段解析成功但未找到test_cases字段")
            else:
                logger.debug("未找到包含test_cases的JSON片段")
        except json.JSONDecodeError as e:
            logger.debug(f"提取JSON片段后解析失败: {e}")

        # 策略5: 增强的JSON提取和修复
        try:
            enhanced_result = self._enhanced_json_extraction(content)
            if enhanced_result:
                logger.info("增强JSON提取成功")
                if 'test_cases' in enhanced_result:
                    logger.info(
                        f"增强JSON提取找到test_cases，包含{len(enhanced_result['test_cases'])}个用例")
                    return enhanced_result
                else:
                    logger.debug("增强JSON提取成功但未找到test_cases字段")
        except Exception as e:
            logger.debug(f"增强JSON提取失败: {e}")

        # 策略6: 正则表达式提取test_cases
        try:
            regex_result = self._regex_extract_test_cases(content)
            if regex_result:
                logger.info("正则表达式提取test_cases成功")
                if 'test_cases' in regex_result:
                    logger.info(
                        f"正则表达式提取找到test_cases，包含{len(regex_result['test_cases'])}个用例")
                    return regex_result
                else:
                    logger.debug("正则表达式提取成功但未找到test_cases字段")
        except Exception as e:
            logger.debug(f"正则表达式提取失败: {e}")

        # 策略7: 分段解析
        try:
            segment_result = self._segment_parse(content)
            if segment_result:
                logger.info("分段解析成功")
                if 'test_cases' in segment_result:
                    logger.info(
                        f"分段解析找到test_cases，包含{len(segment_result['test_cases'])}个用例")
                    return segment_result
                else:
                    logger.debug("分段解析成功但未找到test_cases字段")
        except Exception as e:
            logger.debug(f"分段解析失败: {e}")

        # 策略8: 使用增强JSON解析器作为最后的回退
        try:
            from enhanced_json_parser import EnhancedJSONParser
            enhanced_parser = EnhancedJSONParser()
            result = enhanced_parser.parse(content)
            if result and isinstance(result, dict) and 'test_cases' in result:
                logger.info("增强JSON解析器回退策略成功")
                logger.info(
                    f"增强JSON解析器回退找到test_cases，包含{len(result['test_cases'])}个用例")
                return result
            else:
                logger.debug("增强JSON解析器回退失败或未找到test_cases")
        except Exception as e:
            logger.debug(f"增强JSON解析器回退失败: {e}")

        # 记录内容样本用于调试
        logger.warning("所有解析策略都失败")
        logger.debug(f"解析失败的内容前500字符: {content[:500]}")
        logger.debug(f"解析失败的内容后500字符: {content[-500:]}")

        # 检查内容中是否包含关键字段
        has_test_cases = 'test_cases' in content
        has_id = '"id"' in content or "'id'" in content
        has_title = '"title"' in content or "'title'" in content
        has_steps = '"steps"' in content or "'steps'" in content

        logger.debug(
            f"内容分析 - test_cases: {has_test_cases}, id: {has_id}, title: {has_title}, steps: {has_steps}")

        return None

    def _fix_json_issues(self, content: str) -> Optional[str]:
        """修复常见的JSON问题"""
        try:
            # 修复单引号
            content = content.replace("'", '"')

            # 修复尾随逗号
            content = re.sub(r',\s*}', '}', content)
            content = re.sub(r',\s*]', ']', content)

            # 修复缺少引号的键
            content = re.sub(r'(\w+):', r'"\1":', content)

            # 修复换行符问题
            content = content.replace('\n', '\\n').replace(
                '\r', '\\r').replace('\t', '\\t')

            # 验证修复后的JSON
            json.loads(content)
            return content

        except (json.JSONDecodeError, Exception):
            return None

    def _enhanced_json_extraction(self, content: str) -> Optional[Dict[str, Any]]:
        """增强的JSON提取和修复"""
        try:
            # 查找所有可能的JSON块
            json_patterns = [
                # 简单的test_cases模式
                r'\{[^{}]*"test_cases"[^{}]*\[[^\]]*\][^{}]*\}',
                r'\{.*?"test_cases".*?\[.*?\].*?\}',  # 更宽松的模式
                r'\{[\s\S]*?"test_cases"[\s\S]*?\[[\s\S]*?\][\s\S]*?\}',  # 包含换行的模式
            ]

            for pattern in json_patterns:
                matches = re.findall(pattern, content, re.DOTALL)
                for match in matches:
                    try:
                        # 尝试解析匹配的JSON
                        result = json.loads(match)
                        if isinstance(result, dict) and 'test_cases' in result:
                            return result
                    except json.JSONDecodeError:
                        # 尝试修复后解析
                        fixed = self._fix_json_issues(match)
                        if fixed:
                            try:
                                result = json.loads(fixed)
                                if isinstance(result, dict) and 'test_cases' in result:
                                    return result
                            except json.JSONDecodeError:
                                continue

            # 如果没有找到完整的JSON，尝试构建一个
            return self._construct_json_from_fragments(content)

        except Exception:
            return None

    def _regex_extract_test_cases(self, content: str) -> Optional[Dict[str, Any]]:
        """使用正则表达式提取test_cases"""
        try:
            # 查找test_cases数组
            test_cases_pattern = r'"test_cases"\s*:\s*\[(.*?)\]'
            match = re.search(test_cases_pattern, content, re.DOTALL)

            if not match:
                # 尝试更宽松的模式
                test_cases_pattern = r'test_cases["\s]*:[\s]*\[(.*?)\]'
                match = re.search(test_cases_pattern, content, re.DOTALL)

            if match:
                test_cases_content = match.group(1)

                # 尝试解析test_cases数组
                try:
                    test_cases = json.loads(f'[{test_cases_content}]')
                    return {"test_cases": test_cases}
                except json.JSONDecodeError:
                    # 尝试修复后解析
                    fixed_content = self._fix_json_issues(
                        f'[{test_cases_content}]')
                    if fixed_content:
                        try:
                            test_cases = json.loads(fixed_content)
                            return {"test_cases": test_cases}
                        except json.JSONDecodeError:
                            pass

                # 如果数组解析失败，尝试逐个解析测试用例
                return self._parse_individual_test_cases(test_cases_content)

            return None

        except Exception:
            return None

    def _segment_parse(self, content: str) -> Optional[Dict[str, Any]]:
        """分段解析内容"""
        try:
            # 按行分割内容
            lines = content.split('\n')

            # 查找包含test_cases的行
            test_cases_start = -1
            for i, line in enumerate(lines):
                if 'test_cases' in line and '[' in line:
                    test_cases_start = i
                    break

            if test_cases_start == -1:
                return None

            # 从test_cases开始，找到完整的数组
            brace_count = 0
            bracket_count = 0
            json_lines = []

            for i in range(test_cases_start, len(lines)):
                line = lines[i]
                json_lines.append(line)

                # 计算括号数量
                brace_count += line.count('{') - line.count('}')
                bracket_count += line.count('[') - line.count(']')

                # 如果括号平衡，尝试解析
                if brace_count <= 0 and bracket_count <= 0 and i > test_cases_start:
                    json_content = '\n'.join(json_lines)

                    # 尝试构建完整的JSON
                    if not json_content.strip().startswith('{'):
                        json_content = '{' + json_content
                    if not json_content.strip().endswith('}'):
                        json_content = json_content + '}'

                    try:
                        result = json.loads(json_content)
                        if isinstance(result, dict) and 'test_cases' in result:
                            return result
                    except json.JSONDecodeError:
                        # 尝试修复后解析
                        fixed = self._fix_json_issues(json_content)
                        if fixed:
                            try:
                                result = json.loads(fixed)
                                if isinstance(result, dict) and 'test_cases' in result:
                                    return result
                            except json.JSONDecodeError:
                                continue

            return None

        except Exception:
            return None

    def _construct_json_from_fragments(self, content: str) -> Optional[Dict[str, Any]]:
        """从片段构建JSON"""
        try:
            # 查找所有可能的测试用例片段
            case_patterns = [
                r'"id"\s*:\s*"[^"]*"',
                r'"title"\s*:\s*"[^"]*"',
                r'"preconditions"\s*:\s*"[^"]*"',
                r'"steps"\s*:\s*\[[^\]]*\]',
                r'"priority"\s*:\s*"[^"]*"'
            ]

            found_cases = []

            # 尝试找到测试用例的边界
            lines = content.split('\n')
            current_case = {}

            for line in lines:
                line = line.strip()
                if not line:
                    continue

                # 检查是否包含测试用例字段
                for pattern in case_patterns:
                    match = re.search(pattern, line)
                    if match:
                        field_match = re.search(r'"(\w+)"\s*:\s*(.+)', line)
                        if field_match:
                            field_name = field_match.group(1)
                            field_value = field_match.group(
                                2).strip().rstrip(',')

                            # 尝试解析字段值
                            try:
                                if field_value.startswith('"') and field_value.endswith('"'):
                                    current_case[field_name] = field_value[1:-1]
                                elif field_value.startswith('[') and field_value.endswith(']'):
                                    current_case[field_name] = json.loads(
                                        field_value)
                                else:
                                    current_case[field_name] = field_value.strip(
                                        '"')
                            except:
                                current_case[field_name] = field_value.strip(
                                    '"')

                # 如果找到了一个相对完整的测试用例
                if len(current_case) >= 3 and 'id' in current_case:
                    found_cases.append(current_case.copy())
                    current_case = {}

            # 如果还有未完成的用例
            if len(current_case) >= 2:
                found_cases.append(current_case)

            if found_cases:
                return {"test_cases": found_cases}

            return None

        except Exception:
            return None

    def _parse_individual_test_cases(self, test_cases_content: str) -> Optional[Dict[str, Any]]:
        """逐个解析测试用例"""
        try:
            # 分割测试用例
            cases = []
            brace_count = 0
            current_case = ""

            for char in test_cases_content:
                current_case += char
                if char == '{':
                    brace_count += 1
                elif char == '}':
                    brace_count -= 1
                    if brace_count == 0:
                        # 完成一个测试用例
                        case_content = current_case.strip().rstrip(',')
                        try:
                            case = json.loads(case_content)
                            cases.append(case)
                        except json.JSONDecodeError:
                            # 尝试修复后解析
                            fixed_case = self._fix_json_issues(case_content)
                            if fixed_case:
                                try:
                                    case = json.loads(fixed_case)
                                    cases.append(case)
                                except json.JSONDecodeError:
                                    # 如果还是失败，尝试构建基本用例
                                    basic_case = self._create_basic_test_case(
                                        case_content)
                                    if basic_case:
                                        cases.append(basic_case)
                        current_case = ""

            if cases:
                return {"test_cases": cases}

            return None

        except Exception:
            return None

    def _create_basic_test_case(self, content: str) -> Optional[Dict[str, Any]]:
        """创建基本的测试用例"""
        try:
            case = {
                "id": "TC001",
                "title": "解析失败的测试用例",
                "preconditions": "无",
                "steps": [
                    {
                        "step_number": 1,
                        "description": "请检查原始内容格式",
                        "expected_result": "修复格式问题"
                    }
                ],
                "priority": "P3"
            }

            # 尝试从内容中提取一些信息
            if 'title' in content:
                title_match = re.search(r'"title"\s*:\s*"([^"]*)"', content)
                if title_match:
                    case["title"] = title_match.group(1)

            if 'id' in content:
                id_match = re.search(r'"id"\s*:\s*"([^"]*)"', content)
                if id_match:
                    case["id"] = id_match.group(1)

            return case

        except Exception:
            return None
